public class NotifyTest implements Runnable{
    private boolean flag;
    private Object object;

    NotifyTest(boolean flag,Object o) {
        this.flag = flag;
        this.object = o;
    }
    private void waitThread() {
        synchronized(object) {
            System.out.println(Thread.currentThread().getName() + " wait begin...");
            try {
                object.wait();
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " wait end...");
        }
    }
    private void notifyThread() {
        synchronized(object) {
            System.out.println(Thread.currentThread().getName() + " noitify begin...");
            object.notify();
            System.out.println(Thread.currentThread().getName() + " noitify end...");
        }
        try {
            Thread.sleep(3000);
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }
        synchronized(object) {
            System.out.println(Thread.currentThread().getName() + " noitifyAll begin...");
            object.notifyAll();
            System.out.println(Thread.currentThread().getName() + " noitifyAll end...");
        }
    }
    @Override
    public void run() {
        if(flag) {
            waitThread();
        } else {
            notifyThread();
        }
    }

public static void main(String[] args) throws InterruptedException {
   Object object = new Object();
   NotifyTest test2 = new NotifyTest(false, object);
   Thread thread1 = new Thread(test2,"Thread B");
   for(int i = 0 ;i < 10; i++){
        NotifyTest test1 = new NotifyTest(true, object);
        Thread thread = new Thread(test1,"Thread A " + i);
        thread.start();
   }
   Thread.sleep(1000);
   thread1.start();
}
}